# 错误处理模块
import traceback
import uuid
from functools import wraps
from flask import current_app, request, render_template, jsonify, redirect, url_for, flash
from werkzeug.exceptions import HTTPException
from flask_login import current_user


def handle_errors(f):
    """
    通用错误处理装饰器
    捕获视图函数中的异常并处理
    """
    @wraps(f)
    def decorated_function(*args, **kwargs):
        try:
            return f(*args, **kwargs)
        except HTTPException as e:
            # HTTP异常直接抛出，由Flask的错误处理器处理
            raise e
        except Exception as e:
            # 记录错误信息
            error_id = str(uuid.uuid4())[:8]  # 生成简短的错误ID
            current_app.logger.error(f"Error ID: {error_id} - {str(e)}\n{traceback.format_exc()}")
            
            # 如果是AJAX请求，返回JSON错误
            if request.headers.get('X-Requested-With') == 'XMLHttpRequest':
                return jsonify({
                    'success': False,
                    'message': '服务器内部错误',
                    'error_id': error_id
                }), 500
            
            # 普通请求，渲染错误页面
            return render_template('errors/500.html', error_id=error_id), 500
    
    return decorated_function


def admin_required(f):
    """
    管理员权限装饰器
    检查用户是否具有管理员权限
    """
    @wraps(f)
    def decorated_function(*args, **kwargs):
        if not current_user.is_authenticated:
            flash('请先登录', 'error')
            return redirect(url_for('profile.login', next=request.url))
        
        if not hasattr(current_user, 'is_admin') or not current_user.is_admin:
            flash('您没有权限访问此页面', 'error')
            return render_template('errors/403.html'), 403
        
        return f(*args, **kwargs)
    
    return decorated_function


def login_required_custom(f):
    """
    自定义登录要求装饰器
    与flask_login的login_required类似，但增加了AJAX支持
    """
    @wraps(f)
    def decorated_function(*args, **kwargs):
        if not current_user.is_authenticated:
            # 如果是AJAX请求，返回JSON错误
            if request.headers.get('X-Requested-With') == 'XMLHttpRequest':
                return jsonify({
                    'success': False,
                    'message': '请先登录',
                    'login_required': True
                }), 401
            
            # 保存原始URL以便登录后重定向
            flash('请先登录', 'error')
            return redirect(url_for('profile.login', next=request.url))
        
        return f(*args, **kwargs)
    
    return decorated_function


def permission_required(permission):
    """
    权限检查装饰器
    检查用户是否具有特定权限
    
    Args:
        permission (str): 所需的权限名称
    """
    def decorator(f):
        @wraps(f)
        def decorated_function(*args, **kwargs):
            if not current_user.is_authenticated:
                flash('请先登录', 'error')
                return redirect(url_for('profile.login', next=request.url))
            
            # 检查用户是否有所需权限
            if not hasattr(current_user, 'has_permission') or not current_user.has_permission(permission):
                flash('您没有权限访问此页面', 'error')
                return render_template('errors/403.html'), 403
            
            return f(*args, **kwargs)
        
        return decorated_function
    return decorator


def rate_limit(max_requests=5, period=60, scope_func=lambda: request.remote_addr):
    """
    简单的速率限制装饰器
    
    Args:
        max_requests (int): 在指定时间段内允许的最大请求数
        period (int): 时间段（秒）
        scope_func (callable): 用于确定限制范围的函数，默认为IP地址
    """
    def decorator(f):
        @wraps(f)
        def decorated_function(*args, **kwargs):
            # 这里应该实现速率限制逻辑
            # 可以使用Redis或其他存储来跟踪请求计数
            # 简化实现，仅作为示例
            
            # 在实际应用中，这里应该检查请求计数
            # 如果超过限制，返回429错误
            # if request_count > max_requests:
            #     return render_template('errors/429.html'), 429
            
            return f(*args, **kwargs)
        
        return decorated_function
    return decorator


def validate_json(required_fields=None):
    """
    JSON数据验证装饰器
    
    Args:
        required_fields (list): 必需的字段列表
    """
    def decorator(f):
        @wraps(f)
        def decorated_function(*args, **kwargs):
            # 检查请求是否为JSON
            if not request.is_json:
                return jsonify({
                    'success': False,
                    'message': '请求必须是JSON格式'
                }), 400
            
            # 获取JSON数据
            data = request.get_json()
            if not data:
                return jsonify({
                    'success': False,
                    'message': '无效的JSON数据'
                }), 400
            
            # 检查必需字段
            if required_fields:
                missing_fields = [field for field in required_fields if field not in data]
                if missing_fields:
                    return jsonify({
                        'success': False,
                        'message': f'缺少必需字段: {", ".join(missing_fields)}'
                    }), 400
            
            return f(*args, **kwargs)
        
        return decorated_function
    return decorator